/***
 * 粒子效果：雨、雪、雾
 */

// export var myRain, mySnow, myFog
export function addPostProcessStage(viewer, name, type) {
	let stage = getStage(viewer, name);
	let fs = null;
	let uniform = null;
	if (!stage) {
		switch (type) {
			case 'snow':
				fs = fs_snow();
				uniform = {
					speed: 0.2,
					// density: 5,
					density: 0.5,
					snowSize: 15
				};
				break;
			case 'rain':
				fs = fs_rain();
				uniform = {
					speed: 0.2,
					density: 0.3
				};
				break;
			case 'fog2':
				fs = fs_fog2();
				uniform = {
					speed: 0.2,
					density: 30
				};
				break;
			case 'fog':
				fs = fs_fog();
				uniform = {
					fogByDistance: new Cesium.Cartesian4(10.0, 0.0, 1500, 1.0),
					fogColor: new Cesium.Color(1.0, 1.0, 1.0, 1.0)
				};
				break;
		}
	}
	stage = new Cesium.PostProcessStage({
		name: name,
		fragmentShader: fs,
		uniforms: uniform
	});
	return viewer.scene.postProcessStages.add(stage);
}
export function removePostProcessStage(viewer, name) {
	const stage = getStage(viewer, name);
	if (stage) {
		viewer.scene.postProcessStages.remove(stage);
	}
}
function getStage(viewer, name) {
	let stage = null;
	const stages = viewer.scene.postProcessStages;
	for (let i = 0; i < stages._stages.length; i++) {
		const tmp = stages.get(i);
		if (tmp.name === name) {
			stage = tmp;
			break;
		}
	}
	return stage;
}
// 雨雪雾的着色器
function fs_snow() {
	return (
		'uniform sampler2D colorTexture;\n' +
		'varying vec2 v_textureCoordinates;\n' +
		'uniform float speed;\n' +
		'uniform float density;\n' +
		'uniform int snowSize;\n' +
		'float snow(vec2 uv,float scale)\n' +
		'{\n' +
		'    float time = czm_frameNumber / 60.0;\n' +
		'    float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n' +
		'    uv+=time/scale;uv.y+=cos(.0)*time*speed*20./scale;uv.x+=sin(uv.y+sin(.0)*time*speed*20.)/scale;\n' +
		'    uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n' +
		'    p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n' +
		'    k=smoothstep(0.,k,sin(f.x+f.y)*0.01);\n' +
		'    return k*w*clamp(float(snowSize) / 5.0, 1.0, 5.0);\n' +
		'}\n' +
		'void main(void){\n' +
		'     vec2 resolution = czm_viewport.zw;\n' +
		'     vec2 uv=(gl_FragCoord.xy*1.-resolution.xy)/min(resolution.x,resolution.y);\n' +
		'     vec3 finalColor=vec3(0);\n' +
		'     float c = 0.0;\n' +
		'     int d = int (density*20.0);\n' +
		'     for(int i = 2; i < 5; i++){\n' +
		'     if(d < i){\n' +
		'     break;\n' +
		'     }\n' +
		'     c+=snow(uv,float(i));\n' +
		'     }\n' +
		'     for (int i = 6; i < 10; i+=2){\n' +
		'     if(d < i){\n' +
		'     break;\n' +
		'     }\n' +
		'     c+=snow(uv,float(i));\n' +
		'     }\n' +
		'     for(int i = 15; i < 30;i+=5){\n' +
		'     if(d < i){\n' +
		'     break;\n' +
		'     }\n' +
		'     c+=snow(uv,float(i));\n' +
		'     }\n' +
		'     finalColor=vec3(c);\n' +
		'     if(c > 0.8){\n' +
		'     finalColor = vec3(max(5.0, c));\n' +
		'     }\n' +
		'     gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1.), 0.15);\n' +
		'}'
	);
}
function fs_rain() {
	return (
		'uniform sampler2D colorTexture;\n' +
		'varying vec2 v_textureCoordinates;\n' +
		'uniform float speed;\n' +
		'uniform float density;\n' +
		'float hash(float x){\n' +
		'     return fract(sin(x*133.3)*13.13);\n' +
		' }\n' +
		'void main(void){\n' +
		'     float time = czm_frameNumber / 30.0;\n' +
		'     vec2 resolution = czm_viewport.zw; \n' +
		'     vec2 uv=(gl_FragCoord.xy*2.0-resolution.xy)/min(resolution.x,resolution.y);\n' +
		'     vec3 c=vec3(.6,.7,.9); \n' +
		'     float a=-.0;\n' +
		'     float si=sin(a),co=cos(a);\n' +
		'     uv*=mat2(co,-si,si,co);\n' +
		'     uv*=length(uv+vec2(0,4.9))*.3+1.;\n' +
		'     float v=1.-sin(hash(floor(uv.x*100.))*2.0);\n' +
		'     float b=clamp(abs(sin(25.0*speed*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*density*100.0;\n' +
		'     c*=v*b; \n' +
		'     gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), speed<0.00001?0.0:0.5); \n' +
		'}'
	);
}
function fs_fog2() {
	return (
		'uniform sampler2D colorTexture;\n' +
		'  uniform sampler2D depthTexture;\n' +
		'  varying vec2 v_textureCoordinates;\n' +
		'  void main(void)\n' +
		'  {\n' +
		'      vec4 origcolor=texture2D(colorTexture, v_textureCoordinates);\n' +
		'      vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);\n' +
		'      float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n' +
		'      vec4 depthcolor=texture2D(depthTexture, v_textureCoordinates);\n' +
		'      float f=(depthcolor.r-0.22)/0.2;\n' +
		'      if(f<0.0) f=0.0;\n' +
		'      else if(f>1.0) f=1.0;\n' +
		'      gl_FragColor = mix(origcolor,fogcolor,f);\n' +
		'   }'
	);
}
function fs_fog() {
	return (
		'float getDistance(sampler2D depthTexture, vec2 texCoords) \n' +
		'{ \n' +
		'    float depth = czm_unpackDepth(texture2D(depthTexture, texCoords)); \n' +
		'    if (depth == 0.0) { \n' +
		'        return czm_infinity; \n' +
		'    } \n' +
		'    vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth); \n' +
		'    return -eyeCoordinate.z / eyeCoordinate.w; \n' +
		'} \n' +
		'//计算雾化距离（当它远离眼睛位置时，系数变小）\n' +
		'float interpolateByDistance(vec4 nearFarScalar, float distance) \n' +
		'{ \n' +
		'    float startDistance = nearFarScalar.x;//雾化的起点距离 \n' +
		'    float startValue = nearFarScalar.y; \n' +
		'    float endDistance = nearFarScalar.z; \n' +
		'    float endValue = nearFarScalar.w; \n' +
		'    float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0); \n' +
		'    return mix(startValue,endValue,t ); \n' +
		'} \n' +
		'vec4 alphaBlend(vec4 sourceColor, vec4 destinationColor) \n' +
		'{ \n' +
		'    return sourceColor * vec4(sourceColor.aaa, 1.0) + destinationColor * (1.0 - sourceColor.a); \n' +
		'} \n' +
		'uniform sampler2D colorTexture; \n' +
		'uniform sampler2D depthTexture; \n' +
		'uniform vec4 fogByDistance; \n' +
		'uniform vec4 fogColor; //雾的颜色\n' +
		'varying vec2 v_textureCoordinates; \n' +
		'void main(void) \n' +
		'{ \n' +
		'    float distance = getDistance(depthTexture, v_textureCoordinates); \n' +
		'    vec4 sceneColor = texture2D(colorTexture, v_textureCoordinates); \n' +
		'    float blendAmount = interpolateByDistance(fogByDistance, distance); \n' +
		'    vec4 finalFogColor = vec4(fogColor.rgb, fogColor.a * blendAmount); \n' +
		'    gl_FragColor = alphaBlend(finalFogColor, sceneColor); \n' +
		'} \n'
	);
}
